/* http://dm.ing.unibs.it/giuzzi/corsi/2010-11/Brescia/Algebra_Codici_Crittografia/papers/Coin_flipping.pdf */

#include "stdafx.h"

#include "../Lab1_Large_numbers/__uintX2.h"
#include "../Lab3_Primality_test/poklington_test.h"

using std::cout;
using std::endl;


// the program simulates coin flipping via phone
// in this case describes situation when Alice chooze 
// heads or tails and Bob make the coin flipping itself

int main()
{
    // -- 0. Preparation phase -- //
    cout << "0. Preparation phase...\n\n";
    // start the random counter
    srand(int(time(NULL)));

    // get public group and generator
	uint128 p, g;
	p = poklington().get_prime(sizeof(uint128)*8, g);


    // -- 1. Commit phase -- //
    cout << "1. Commit phase.\n\n";

    // Alice chooses random bit from {0, 1} 
	uint128 b = uint128::random() % 2;

	// ... chooses random number, make it even
	uint128 temp = uint128::random();
	// and x: x % 2 == b
    uint128 x = ((temp % 2==0) ? temp : temp - 1) + b;
    cout << "\tA: b = " << b << "; x = " << x << endl;
    
    // Alice compute blob to send it Bob
	uint128 r = uint128::pow_m(g, x, p);

    // Alice send the blob to Bob
    // A --> B: r
    cout << "\tA --> B: r = " << r << endl;


    // -- 2. Reveal phase -- //
    cout << "2. Reveal phase.\n";

    // Alice sends x to Bob to confirm choosen bit
    // A --> B: x

    cout << "\tA --> B: x = " << x << endl << endl;

    // Bob gets choosen bit b
    cout << "\tB: b = " << x % 2 << endl;

    // Bob compute r to make sure Alice not cheating
	uint128 r_revealed = uint128::pow_m(g, x, p);
	cout << "\tB: r = " << r_revealed << endl;
	cout << "\tB: r is " << ((r_revealed==r)?("right"):("wrong")) << endl;

	system("pause");
	return 0;
}
